package com.project.class8_24.proxy.transactional.service.impl;

import com.project.class8_24.proxy.transactional.dao.impl.BaseDao;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;

public class ServiceProxy implements InvocationHandler {
    private Object targetObj;
    public ServiceProxy(Object targetObj){
        this.targetObj = targetObj;
    }

    public Object getProxy(){
        return Proxy.newProxyInstance(targetObj.getClass().getClassLoader(),
                targetObj.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Connection con = this.getConnection();
        //设置为手动提交
        con.setAutoCommit(false);
        Field[] fieldArray = targetObj.getClass().getDeclaredFields();
        for(Field f : fieldArray){
            //去掉修饰符检查
            f.setAccessible(true);
            //得到属性的值
            Object value = f.get(targetObj);
            //判断是否为持久组件
            if(value instanceof BaseDao){
                BaseDao baseDao = (BaseDao) value;
                //设置连接对象，保证所有持久组件使用同一个连接
                baseDao.setConnection(con);
            }
        }

        Object returnObj = null;
        try {
            //执行目标方法
             returnObj = method.invoke(targetObj, args);

            //事务提交
            con.commit();
        }catch (Exception e){
            e.printStackTrace();
            //回滚事务
            con.rollback();
        }finally{
            con.close();
        }


        return returnObj;
    }

    private Connection getConnection(){
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost:12345/mydb?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false",
                "root","lovo");
            return con;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
